package com.mlethe.library.socialtool.core;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;

import com.mlethe.library.socialtool.callback.OauthActionListener;
import com.mlethe.library.socialtool.callback.PayActionListener;
import com.tencent.connect.UserInfo;
import com.tencent.connect.auth.AuthAgent;
import com.tencent.connect.common.Constants;
import com.tencent.mobileqq.openpay.api.IOpenApi;
import com.tencent.mobileqq.openpay.api.IOpenApiListener;
import com.tencent.mobileqq.openpay.api.OpenApiFactory;
import com.tencent.mobileqq.openpay.constants.OpenConstants;
import com.tencent.mobileqq.openpay.data.base.BaseResponse;
import com.tencent.mobileqq.openpay.data.pay.PayApi;
import com.tencent.mobileqq.openpay.data.pay.PayResponse;
import com.tencent.tauth.IUiListener;
import com.tencent.tauth.Tencent;
import com.tencent.tauth.UiError;

import org.json.JSONObject;

/**
 * QQ登录
 *
 * @author Mlethe
 */
public class QQ implements Oauth<Tencent> {

    private Tencent mTencent;
    private IOpenApi mOpenApi;

    private Context mContext;
    private String mAppid;

    private BaseUiListener listener;
    private BaseUiListener userInfoListener;

    private OpenApiListener mOpenApiListener;

    private OauthActionListener mOauthListener;
    private PayActionListener mPayListener;

    /**
     * @param context
     * @param appid   腾讯开放平台 appid
     */
    public QQ(Context context, String appid) {
        this.mContext = context;
        this.mAppid = appid;
        listener = new BaseUiListener();
        userInfoListener = new BaseUiListener() {
            @Override
            public void onComplete(Object o) {
                if (mOauthListener == null) {
                    return;
                }
                try {
                    String openId = mTencent.getOpenId();
                    JSONObject jsonObject = (JSONObject) o;
                    jsonObject.put("openid", openId);
                    mOauthListener.onComplete(Platform.QQ, jsonObject);
                    mOauthListener = null;
                } catch (Exception e) {
                    mOauthListener.onFail(Platform.QQ);
                    mOauthListener = null;
                    e.printStackTrace();
                }
            }
        };
    }

    /**
     * 授权登录回调
     * 请在调用 oauth() 方法前调用
     *
     * @param listener listener
     * @return
     */
    public QQ setOauthActionListener(OauthActionListener listener) {
        this.mOauthListener = listener;
        return this;
    }

    /**
     * 授权登录(所有权限)
     *
     * @param activity 调用者activity。应用使用SDK时，会从应用自己的Activity跳转到SDK的Activity，应用调用SDK的Activity即为这里的调用者activity。
     * @param qrcode   是否开启二维码登录，没有安装手Q时候使用二维码登录，一般用电视等设备。
     */
    public void oauth(Activity activity, boolean qrcode) {
        oauth(activity, "all", qrcode);
    }

    /**
     * 授权登录(所有权限)
     *
     * @param activity 调用者activity。应用使用SDK时，会从应用自己的Activity跳转到SDK的Activity，应用调用SDK的Activity即为这里的调用者activity。
     */
    public void oauth(Activity activity) {
        oauth(activity, "all");
    }

    /**
     * 授权登录(禁止开启二维码登录)
     *
     * @param activity 调用者activity。应用使用SDK时，会从应用自己的Activity跳转到SDK的Activity，应用调用SDK的Activity即为这里的调用者activity。
     * @param scope    应用需要获得哪些接口的权限，由“，”分隔。例如： SCOPE = “get_simple_userinfo,add_topic”；所有权限用“all”
     */
    public void oauth(Activity activity, String scope) {
        oauth(activity, scope, false);
    }

    /**
     * 授权登录
     *
     * @param activity 调用者activity。应用使用SDK时，会从应用自己的Activity跳转到SDK的Activity，应用调用SDK的Activity即为这里的调用者activity。
     * @param scope    应用需要获得哪些接口的权限，由“，”分隔。例如： SCOPE = “get_simple_userinfo,add_topic”；所有权限用“all”
     * @param qrcode   是否开启二维码登录，没有安装手Q时候使用二维码登录，一般用电视等设备。
     */
    public void oauth(Activity activity, String scope, boolean qrcode) {
        if (!getApi().isSessionValid()) {
            if (qrcode) {
                activity.getIntent().putExtra(AuthAgent.KEY_FORCE_QR_LOGIN, true);
            }
            getApi().login(activity, scope, listener, qrcode);
        } else {
            getApi().logout(activity);
            oauth(activity, scope, qrcode);
        }
    }

    /**
     * 接收授权成功后返回的数据
     * 注意：在调用login的Activity或者Fragment重写onActivityResult方法
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == Constants.REQUEST_LOGIN) {
            Tencent.onActivityResultData(requestCode, resultCode, data, listener);
        }
    }

    /**
     * 初始化token和openid
     *
     * @param jsonObject
     */
    private void initOpenidAndToken(JSONObject jsonObject) {
        try {
            String token = jsonObject.getString(Constants.PARAM_ACCESS_TOKEN);
            String expires = jsonObject.getString(Constants.PARAM_EXPIRES_IN);
            String openId = jsonObject.getString(Constants.PARAM_OPEN_ID);
            if (!TextUtils.isEmpty(token) && !TextUtils.isEmpty(expires)
                    && !TextUtils.isEmpty(openId)) {
                mTencent.setAccessToken(token, expires);
                mTencent.setOpenId(openId);
            }
        } catch (Exception e) {
            if (mOauthListener != null) {
                mOauthListener.onFail(Platform.QQ);
                mOauthListener = null;
            }
            e.printStackTrace();
        }
    }

    /**
     * 获取用户信息
     */
    private void getUserInfo() {
        if (mTencent != null && mTencent.isSessionValid()) {
            UserInfo info = new UserInfo(mContext, mTencent.getQQToken());
            info.getUserInfo(userInfoListener);
        } else {
            if (mOauthListener != null) {
                mOauthListener.onFail(Platform.QQ);
                mOauthListener = null;
            }
        }
    }

    /**
     * 调起QQ钱包支付
     *
     * @param appId          在http://open.qq.com注册的AppId,参与支付签名
     * @param serialNumber   支付序号,用于标识此次支付
     * @param callbackScheme QQ钱包支付结果回调给urlscheme为callbackScheme的activity
     * @param tokenId        QQ钱包支付生成的token_id
     * @param pubAcc         手Q公众帐号id.参与支付签名
     * @param pubAccHint     支付完成页面，展示给用户的提示语：提醒关注公众帐号
     * @param nonce          随机字段串，每次支付时都要不一样.参与支付签名
     * @param timeStamp      时间戳，为1970年1月1日00:00到请求发起时间的秒数
     * @param bargainorId    商户号.参与支付签名
     * @param sign           商户Server下发的数字签名，生成的签名串
     */
    public void pay(String appId, String serialNumber, String callbackScheme, String tokenId, String pubAcc, String pubAccHint, String nonce, long timeStamp, String bargainorId, String sign) {
        if (!isAppPayInstalled() || !isCanPay()) {
            if (mPayListener != null) {
                mPayListener.onNotInstalled(Platform.QQ);
                mPayListener = null;
            }
            return;
        }
        PayApi api = new PayApi();
        api.appId = appId;
        api.serialNumber = serialNumber;
        api.callbackScheme = callbackScheme;
        api.tokenId = tokenId;
        api.pubAcc = pubAcc;
        api.pubAccHint = pubAccHint;
        api.nonce = nonce;
        api.timeStamp = timeStamp;
        api.bargainorId = bargainorId;
        api.sig = sign;
        // 签名时，使用的加密方式，默认为"HMAC-SHA1"
        api.sigType = "HMAC-SHA1";

        if (api.checkParams()) {
            getOpenApi().execApi(api);
        } else {
            if (mPayListener != null) {
                mPayListener.onFail(Platform.QQ);
                mPayListener = null;
            }
        }
    }

    /**
     * 支付回调
     * 请在调用 pay() 方法前调用
     *
     * @param listener listener
     * @return
     */
    public QQ setPayActionListener(PayActionListener listener) {
        this.mPayListener = listener;
        return this;
    }

    /**
     * 支付结果处理
     *
     * @return
     */
    public boolean handleIntent(Intent intent) {
        try {
            return getOpenApi().handleIntent(intent, mOpenApiListener);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * QQ 支付 api
     *
     * @return
     */
    private IOpenApi getOpenApi() {
        if (mOpenApi == null) {
            mOpenApi = OpenApiFactory.getInstance(mContext, mAppid);
        }
        if (mOpenApiListener == null) {
            mOpenApiListener = new OpenApiListener();
        }
        return mOpenApi;
    }

    /**
     * 判断是否安装
     *
     * @return
     */
    private boolean isAppPayInstalled() {
        if (getOpenApi() == null || !getOpenApi().isMobileQQInstalled()) {
            return false;
        }
        return true;
    }

    /**
     * 判断是否支持支付
     * @return
     */
    private boolean isCanPay() {
        if (getOpenApi() == null || !getOpenApi().isMobileQQSupportApi(OpenConstants.API_NAME_PAY)) {
            return false;
        }
        return true;
    }

    @Override
    public Tencent getApi() {
        if (mTencent == null) {
            mTencent = Tencent.createInstance(mAppid, mContext);
        }
        return mTencent;
    }

    /**
     * 判断是否安装
     *
     * @return
     */
    @Override
    public boolean isAppInstalled() {
        if (getApi() == null || !getApi().isQQInstalled(mContext)) {
            return false;
        }
        return true;
    }

    @Override
    public void unregister() {
        if (mTencent != null) {
            mTencent.releaseResource();
            mTencent = null;
        }
    }

    /**
     * 释放内存
     */
    @Override
    public void release() {
        mContext = null;
        unregister();
        listener = null;
        userInfoListener = null;
        mOauthListener = null;
        mOpenApiListener = null;
        mPayListener = null;
        mOpenApi = null;
    }

    private class BaseUiListener implements IUiListener {

        @Override
        public void onComplete(Object o) {
            initOpenidAndToken((JSONObject) o);
            getUserInfo();
        }

        @Override
        public void onError(UiError uiError) {
            if (mOauthListener != null) {
                mOauthListener.onFail(Platform.QQ);
                mOauthListener = null;
            }
        }

        @Override
        public void onCancel() {
            if (mOauthListener != null) {
                mOauthListener.onCancel(Platform.QQ);
                mOauthListener = null;
            }
        }
    }

    /**
     * 回调处理类
     */
    private class OpenApiListener implements IOpenApiListener {

        @Override
        public void onOpenResponse(BaseResponse baseResponse) {
            handleResult(baseResponse);
        }
    }

    /**
     * 处理返回结果
     */
    public void handleResult(BaseResponse response) {
        try {
            if (response instanceof PayResponse) {
                if (mPayListener == null) {
                    return;
                }
                PayResponse payResponse = (PayResponse) response;
                if (payResponse.isSuccess()) {
                    // 支付成功
                    if (payResponse.isPayByWeChat()) {
                        // 微信支付
                        mPayListener.onFail(Platform.QQ);
                    } else {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("apiName", payResponse.apiName);
                        jsonObject.put("serialNumber", payResponse.serialNumber);
                        jsonObject.put("retMsg", payResponse.retMsg);
                        jsonObject.put("transactionId", payResponse.transactionId);
                        jsonObject.put("payTime", payResponse.payTime);
                        jsonObject.put("callbackUrl", payResponse.callbackUrl);
                        jsonObject.put("totalFee", payResponse.totalFee);
                        jsonObject.put("spData", payResponse.spData);
                        mPayListener.onComplete(Platform.QQ, jsonObject);
                    }
                }
                if (payResponse.retCode == -1) {
                    // 用户取消
                    mPayListener.onCancel(Platform.QQ);
                }
                if (payResponse.retCode == -2) {
                    // 登录态超时
                    mPayListener.onCancel(Platform.QQ);
                }
                if (payResponse.retCode == -3) {
                    // 重复提交订单
                    mPayListener.onCancel(Platform.QQ);
                } else {
                    mPayListener.onFail(Platform.QQ);
                }
            } else {
                mPayListener.onFail(Platform.QQ);
            }
            mPayListener = null;
        } catch (Exception e) {
            e.printStackTrace();
            mPayListener = null;
        }
    }
}
